package org.jsequences.reflect;

import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken;

/**
 * An abstract class which calls the default constructor method of a class by reflection. Use this
 * class to create Method-References in a concise way:
 * 
 * <pre class="code">
 * <code class="java">
 * public class Person {
 *   public Person(){}
 *   
 *   public static final Supplier&lt;Person&gt; CONSTRUCTOR = 
 *     new ConstructorSupplier&lt;Person&gt;(){};
 * }
 * </code>
 * </pre>
 * <p>
 * <b>Usage notes:</b> Instantiate this class <b>ONLY</b> in static final constants! Since the
 * initialization phase is unsafe thanks to reflection, refactorings might break the code.
 * Therefore, ensure that the Function is a constant and stays <b>as close to the method declaration
 * as possible</b>! After the static initialization is successful, the function is completely
 * typesafe and nearly as fast as implementing the anonymous function by hand. <i>As long as you
 * adhere to these guidelines, no refactoring should omit your reflective method and if it is, the
 * error is fail-fast and trivial to detect!</i>
 * <p>
 * <b>Implementation notes:</b> This class is abstract but without a single member to force all
 * users to instantiate it with an empty block {} as shown above. This is a technique called
 * "generic type capture", see {@link TypeToken}.
 * 
 * @param <R> the class and constructor type
 * @author Eric Giese
 */
public class ConstructorSupplier<R> extends ReflectionMethod<R, R> implements Supplier<R> {

    /**
     * Instantiates this abstract type.
     */
    protected ConstructorSupplier() {
        initConstructor();
    }

    /**
     * Calls the constructor and returns a new instance.
     * 
     * @return the instance
     */
    @Override
    public final R get() {
        return invoke(null);
    }

    /**
     * ConstructorSuppliers are equal only to other ConstructorSuppliers.
     */
    @Override
    protected final boolean canEqual(Object other) {
        return other instanceof ConstructorSupplier;
    }
}
